package guo

import (
	"log"
	"net/http"
	"strings"
)

type HandlerFunc func(*Context)

type Engine struct{
	*RouteGroup
	router *router
	groups []*RouteGroup
}
type RouteGroup struct {
	prefix string
	middlewares []HandlerFunc
	parent *RouteGroup
	engine *Engine
}

func New() *Engine{
	engine:=&Engine{router:newRouter()}
	engine.RouteGroup=&RouteGroup{engine:engine}
	engine.groups=[]*RouteGroup{engine.RouteGroup}
	return engine
}
func Default() *Engine{
	engine:=New()
	engine.Use(Recovery())
	engine.Use(Logger())
	return engine
}
func (group *RouteGroup) Group(prefix string)*RouteGroup{
	engine:=group.engine
	newGroup:=&RouteGroup{
		prefix:group.prefix+prefix,
		parent: group,
		engine:engine,
	}
	engine.groups=append(engine.groups,newGroup)
	return newGroup
}
func (group *RouteGroup) addRoute(method string,comp string, handler HandlerFunc){
	pattern:=group.prefix+comp
	log.Printf("route %4s - %s",method,pattern)
	group.engine.router.addRouter(method,pattern,handler)
}
func (group *RouteGroup) GET(pattern string, handler HandlerFunc) {
	group.addRoute("GET", pattern, handler)
}
func (group *RouteGroup) POST(pattern string, handler HandlerFunc) {
	group.addRoute("POST", pattern, handler)
}
func (engine *Engine) addRoute(method string,pattern string, handler HandlerFunc){

	log.Printf("route %4s - %s",method,pattern)
	engine.router.addRouter(method,pattern,handler)
}
func (engine *Engine) GET(pattern string,handler HandlerFunc){
	engine.addRoute("GET",pattern,handler)
}
func (engine *Engine) POST(pattern string,handler HandlerFunc){
	engine.addRoute("POST",pattern,handler)
}
func (engine *Engine) Run(addr string) (err error){
	return http.ListenAndServe(addr,engine)
}
func (group *RouteGroup) Use(middlewares ...HandlerFunc){
	group.middlewares=append(group.middlewares,middlewares...)
}
func (engine *Engine) ServeHTTP(w http.ResponseWriter,req *http.Request){
	var middlewares []HandlerFunc
	for _,group:=range engine.groups{
		if strings.HasPrefix(req.URL.Path,group.prefix){
			middlewares=append(middlewares,group.middlewares...)
		}
	}
	c:=newContext(w,req)
	c.handlers=middlewares
	engine.router.handle(c)
}